#include "threadPool.h"
#include <iostream>
#include <cstring>
#include <unistd.h>

#define DEFAULT_MIN_THREADS 3
#define DEFAULT_MAX_THREADS 5
#define DEFAULT_QUEUE_CAPACITY 8
#define DEFAULT_INCREASE_NUM 2

/* 工作线程 */
/* 消费者 */
void *workThreadFunc(void *arg)
{
    pthread_detach(pthread_self());
    ThreadPool * pool = (ThreadPool *)arg;
    
    while(1)
    {
        /* 核心目标: 从任务队列取任务 */
        pthread_mutex_lock(&pool->m_mutex);
        while(pool->m_queueSize == 0)
        {
            /* 等待条件变量 */
            pthread_cond_wait(&pool->m_notEmpty,&pool->m_mutex);

            if((pool->m_exitNum > 0) && (pool->m_aliveThreads > pool->m_minThreads))
            {

                for(int idx = 0;idx < pool->m_maxThreads;idx++)
                {
                    if(pool->m_threadIds[idx] == pthread_self())
                    {
                        (pool->m_aliveThreads)--;
                        (pool->m_exitNum)--;
                        pool->m_threadIds[idx] = 0;
                        break;
                    }
                }
                /* 解锁 */
                pthread_mutex_unlock(&(pool->m_mutex));

                /* 线程退出 */
                pthread_exit(NULL);
                
            }
        }

        /* 程序执行到这个地方: 说明队列里有任务 */
        /* 取任务队列队头元素 */
        Task_t newTask;
        newTask.function = pool->m_queue[pool->m_queueFront].function;
        newTask.arg = pool->m_queue[pool->m_queueFront].arg;

       

        /* 移动队头元素 */
        pool->m_queueFront = (pool->m_queueFront + 1) % pool->m_queueCacity;
        /* 任务队列的元素个数减一 */
        (pool->m_queueSize)--;

        /* 解锁 */
        pthread_mutex_unlock(&(pool->m_mutex));


        /* 加锁 */
        pthread_mutex_lock(&(pool->m_busyMutex));
        /* 忙碌的线程数++ */
        (pool->m_busyThreads)++;
        /* 解锁 */
        pthread_mutex_unlock(&(pool->m_busyMutex));

        /* 执行任务 */
        newTask.function(newTask.arg);
        
        /* 加锁 */
        pthread_mutex_lock(&(pool->m_busyMutex));
        /* 忙碌的线程数-- */
        (pool->m_busyThreads)--;
        /* 解锁 */
        pthread_mutex_unlock(&(pool->m_busyMutex));

        /* 发信号 */
        pthread_cond_signal(&pool->m_notFull);


    }
}

/* 管理者线程 */
void *manageThreadFunc(void *arg)
{
    /* 线程分离 */
    pthread_detach(pthread_self());

    ThreadPool *pool = (ThreadPool *)arg;

    while(true)
    {
        sleep(1);

        /* 加锁 */
        pthread_mutex_lock(&(pool->m_mutex));
        int queueSize = pool->m_queueSize;
        int aliveThreadNums = pool->m_aliveThreads;
        /* 解锁 */
        pthread_mutex_unlock(&(pool->m_mutex));

        /* 加锁 */
        pthread_mutex_lock(&(pool->m_busyMutex));
        int busyThreadNums = pool->m_busyThreads;
        /* 解锁 */
        pthread_mutex_unlock(&(pool->m_busyMutex));

        std::cout << "queueSize : " << queueSize << ", aliveThreadNums :" << aliveThreadNums 
                    << ", busyThreadNums :" << busyThreadNums << std::endl;

        // /* 什么时候需要开辟新的线程 */
        // /* 任务线程数 > 存活线程数 > 忙碌线程数 */
        int ret = 0;
        if(queueSize > (aliveThreadNums - busyThreadNums) && (aliveThreadNums < pool->m_maxThreads))
        {
            int addCnt = 0;
            pthread_mutex_lock(&(pool->m_mutex));
            for(int idx = 0;(idx < pool->m_maxThreads) && (addCnt < DEFAULT_INCREASE_NUM ) && (aliveThreadNums < pool->m_maxThreads);idx++)
            {
                /* 探测 */
                if(pool->m_threadIds[idx] == 0)
                {
                    ret = pthread_create(&(pool->m_threadIds[idx]),NULL,workThreadFunc,pool);
                    if(ret == -1)
                    {
                        perror("thread create error");
                        break;
                    }
                    addCnt++;
                    /* 存活的线程++ */
                    pool->m_aliveThreads++;
                    
                }
            }
            /* 解锁 */
            pthread_mutex_unlock(&(pool->m_mutex));
        }


        /* 什么时候需要减少线程池中线程的数量 */
        /* 任务队列的任务数量 远小于 */
        if((pool->m_queueSize < aliveThreadNums - busyThreadNums) && (aliveThreadNums > pool->m_minThreads))
        {
            /* 加锁 */
            pthread_mutex_lock(&(pool->m_mutex));
            pool->m_exitNum = DEFAULT_INCREASE_NUM;
            for(int idx = 0;idx < DEFAULT_INCREASE_NUM;idx++)
            {
                pthread_cond_signal(&(pool->m_notEmpty));

                usleep(10000);
            }
            /* 解锁 */
            pthread_mutex_unlock(&(pool->m_mutex));
        }

    }
}

/* 构造函数*/
ThreadPool::ThreadPool(int minThread, int maxThread, int maxQueueCapacity)
{
    /* 参数校验 */
    if (minThread < 0 || maxThread < 0 || maxQueueCapacity < 0)
    {
        minThread = DEFAULT_MIN_THREADS;
        maxThread = DEFAULT_MAX_THREADS;
        maxQueueCapacity = DEFAULT_QUEUE_CAPACITY;
    }
    /* 维护住属性 */
    m_minThreads = minThread;
    m_maxThreads = maxThread;
    m_queueCacity = maxQueueCapacity;
    m_busyThreads = 0;


    /* 创建队列 */
    m_queue = new Task_t[m_queueCacity];
    if(m_queue == NULL)
    {
        perror("new queue error ");
        exit(-1);
    }

    /* 清除脏数据 */
    memset(m_queue,0,sizeof(Task_t) * m_queueCacity);

    /* 任务队列的元素个数为0 */
    m_queueSize = 0;
    /* 任务队列的队头 */
    m_queueFront = 0; 
    /* 任务队列的队尾 */
    m_queueRear = 0;
    /* 存活数初始化 */
    m_aliveThreads = 0;
    /* 要删除的线程数 */
    m_exitNum = 0;
    /* 锁 */
    int ret = pthread_mutex_init(&m_mutex,NULL);
    if(ret != 0)
    {
        perror("mutex init error ");
        exit(-1);
    }

    /* 条件变量 */
    ret = pthread_cond_init(&m_notEmpty,NULL);
    if(ret != 0)
    {
        perror("cond init error ");
        exit(-1);
    }
    /* 忙碌线程锁 */
    ret = pthread_mutex_init(&m_busyMutex,NULL);
    if(ret != 0)
    {
        perror("busy mutex init error ");
        exit(-1);
    }

     /* 创建线程池空间 */
    try
    {
        m_threadIds = new pthread_t[maxThread];
        if (m_threadIds == NULL)
        {
            perror(" new error :");
        }
        /* 清除脏数据 */
        memset(m_threadIds, 0, sizeof(pthread_t) * maxThread);
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }
    ret = 0;
    
    for (int idx = 0; idx < m_minThreads; idx++)
    {
        ret = pthread_create(&m_threadIds[idx], NULL, workThreadFunc, this);
        if (ret == -1)
        {
            perror("pthread create error ");
            exit(-1);
        }
        /* 每创建一个线程，存活的线程数加一 */
        m_aliveThreads++;

    }

    /* 管理者线程 */
    m_manageId = 0;
    ret = pthread_create(&m_manageId, NULL, manageThreadFunc, this);
    if (ret == -1)
    {
        perror("manage pthread create error ");
        exit(-1);
    }

}

/* 添加任务 */
/* 生产者 */
void ThreadPool::addTask(void *(*function)(void *arg), void *arg)
{
    if(function == nullptr)
    {
        return;
    }

    /* 将任务添加到队列中 */

    /* 加锁 */
    pthread_mutex_lock(&m_mutex);
    /* 任务个数上限 */
    while(m_queueSize >= m_queueCacity)
    {
        usleep(10000);
        pthread_cond_wait(&m_notFull,&m_mutex);
    }

    /* 程序执行到这个地方 说明队列有位置 */
    m_queue[m_queueRear].function = function;
    m_queue[m_queueRear].arg = arg;
    /* 更新队列尾部 */
    m_queueRear = (m_queueRear + 1) % m_queueCacity;
    /* 任务队列的任务任务数加1*/
    m_queueSize++;

    /* 解锁 */
    pthread_mutex_unlock(&m_mutex);

    /* 发信号 */
    pthread_cond_signal(&m_notEmpty);

   

}
